import pandas as pd
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn


def create_element(name):
    return OxmlElement(name)


def create_attribute(element, name, value):
    element.set(qn(name), value)


def add_numbering_format(doc):
    # 获取文档的编号部分
    numbering_part = doc.part.numbering_part
    if numbering_part is None:
        numbering_part = doc.part._numbering_part()
        doc.part.numbering_part = numbering_part

    # 创建抽象编号
    abstract_num = create_element('w:abstractNum')
    abstract_num_id = len([e for e in numbering_part._element.iter() if e.tag.endswith('abstractNum')])
    create_attribute(abstract_num, 'w:abstractNumId', str(abstract_num_id))

    # 定义每个级别的编号格式
    levels = [
        ('%1.', '1', 0),
        ('%1.%2.', '1', 1),
        ('%1.%2.%3.', '1', 2),
        ('%1.%2.%3.%4.', '1', 3),
        ('%1.%2.%3.%4.%5.', '1', 4),
        ('%1.%2.%3.%4.%5.%6.', '1', 5),
        ('%1.%2.%3.%4.%5.%6.%7.', '1', 6),
        ('%1.%2.%3.%4.%5.%6.%7.%8.', '1', 7),
        ('%1.%2.%3.%4.%5.%6.%7.%8.%9.', '1', 8)
    ]

    for level_num, (format_str, num_fmt, lvl) in enumerate(levels):
        lvl_elem = create_element('w:lvl')
        create_attribute(lvl_elem, 'w:ilvl', str(level_num))
        num_fmt_elem = create_element('w:numFmt')
        create_attribute(num_fmt_elem, 'w:val', num_fmt)
        lvl_text_elem = create_element('w:lvlText')
        create_attribute(lvl_text_elem, 'w:val', format_str)
        # 添加起始编号为 1 的设置
        start_elem = create_element('w:start')
        create_attribute(start_elem, 'w:val', '1')
        lvl_elem.append(num_fmt_elem)
        lvl_elem.append(lvl_text_elem)
        lvl_elem.append(start_elem)
        abstract_num.append(lvl_elem)

    numbering_part._element.append(abstract_num)

    # 创建具体的编号实例
    num = create_element('w:num')
    num_id = len([e for e in numbering_part._element.iter() if e.tag.endswith('num')]) + 1
    create_attribute(num, 'w:numId', str(num_id))
    abstract_num_id_elem = create_element('w:abstractNumId')
    create_attribute(abstract_num_id_elem, 'w:val', str(abstract_num_id))
    num.append(abstract_num_id_elem)
    numbering_part._element.append(num)

    return num_id


def xlsx_to_docx(xlsx_file, docx_file):
    # 读取 Excel 文件
    df = pd.read_excel(xlsx_file)
    # 创建一个新的 Word 文档
    doc = Document()
    # 添加多级编号格式
    num_id = add_numbering_format(doc)
    # 存储每一级标题的上一个标题文本，用于判断是否需要创建新的标题
    last_titles = [None] * (len(df.columns) - 1)

    # 遍历每一行数据
    for index, row in df.iterrows():
        # 获取最后一列作为正文
        content = row.iloc[-1]

        # 遍历前面的列作为标题
        for i, value in enumerate(row[:-1]):
            if pd.notna(value):
                # 如果当前标题和上一个同级别标题不同，则添加新的标题
                if value != last_titles[i]:
                    # 先清除更高级别的标题记录，因为进入了新的分支
                    for j in range(i + 1, len(last_titles)):
                        last_titles[j] = None
                    # 设置标题级别，从 1 到 n - 1
                    heading = doc.add_heading(str(value), level=i + 3)
                    # 为标题添加编号
                    pPr = heading._element.get_or_add_pPr()
                    numPr = pPr.get_or_add_numPr()

                    # 创建并设置 numId 元素
                    numId = create_element('w:numId')
                    create_attribute(numId, 'w:val', str(num_id))
                    numPr.append(numId)

                    # 创建并设置 ilvl 元素
                    ilvl = create_element('w:ilvl')
                    create_attribute(ilvl, 'w:val', str(i+2))
                    numPr.append(ilvl)

                    # 更新当前级别及更高级别的标题记录
                    last_titles[i] = value

        # 添加正文内容
        if pd.notna(content):
            doc.add_paragraph(str(content))

    # 保存 Word 文档
    doc.save(docx_file)


# 调用函数，将 Excel 文件转换为 Word 文档
xlsx_to_docx('/temp/t.xlsx', '/temp/output.docx')
